﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once

//std headers
#include <memory>

// Qt headers
#include <QWidget>
#include <QPointer>

// custom headers
#include "IProjectComponent.h"
#include "SelectionHelper.h"
#include "Major.h"
#include "IPagedData.h"

class QString;
class QPushButton;
class QLineEdit;
class QLabel;
class QTableView;
class QWidget;
class QMenu;
class QMenuBar;
class QAbstractItemModel;
class QStackedLayout;
class QItemSelection;
class QLayout;
class QVBoxLayout;

namespace gmepgcs 
{
    class ProjectComponentsTableModel;
    class CategoriesTreeModel;
    class Bubble;
    class SearchTextBox;
    struct IDetailedProjectComponent;
    class Switcher;
    class Message;
    class ProjectComponentDetailPanel;
    class ListItemModel;
    class CategoriesTreeView;
    struct IGmepGcsCategory;
    class ProjectComponentsTableHeaderView;
    class ProjectComponentItemDelegate;
    class ListItemDelegate;
    class ListHeaderWidget;
}

namespace gmepgcs 
{
    struct CategoryNode
    {
        std::shared_ptr<gmepgcs::IGmepGcsCategory> pData = nullptr;
        std::vector<CategoryNode> vecNode = {};
        int ChildCount = 0;
    };

    class ProjectPage : public QWidget
    {
        Q_OBJECT

    public:
        ProjectPage(QWidget *parent = nullptr, bool isPrivateEnv = false);
        virtual ~ProjectPage();

    public: // refresh
        void Resume();
        void Refresh(bool isCollaborationDocument = true);
        void RefreshCategoryTree(bool isBref = false);
        void RefreshComponentList();
        void RefreshComponent(const std::wstring &projectId, const std::wstring &componentId, const int32_t &componentVersion);

        //public: //for journal
    //    void ReplayProjectComponentOperation(const std::wstring &operation, QAbstractItemModel *model, const QModelIndex &index);
       
    signals:
        void OnProjectComponentEditingPageRequired();
        void OnProjectComponentEditingRequired(const std::wstring &projectId, const std::wstring &enterpriseId, const std::wstring &componentId, const int32_t &componentVersion, const std::wstring &componentName);

    protected:
        virtual bool eventFilter(QObject *obj, QEvent *event) override;
    private: // initialization
        void Init();
        QLayout *InitCategoryTree(QWidget *parent);
        QLayout *InitComponentTable(QWidget *parent);
        QLayout *InitComponentCardList(QWidget *parent);
        QLayout *InitComponentDetailRegion(QWidget *parent);
        
        QLayout *InitMainOperationRegion(QWidget *parent);
        QLayout *InitBatchOperationButtonGroup(QWidget *parent);
        QLayout *InitAddComponentButtonGroup(QWidget *parent);
        QLayout *InitModeSwitchButtonGroup(QWidget *parent);
        
        QLayout *InitSubOperationRegion(QWidget *parent);
        QLayout *InitBubbleButtonGroup(QWidget *parent);

        QLayout *InitNoContentGuideView(QWidget *parent);
        QLayout *InitNoProjectGuideView(QWidget *parent);

    private: // batch operations
        void LoadComponentIntoProjectInBatch();
        void UpdateComponentInBatch();
        void SyncComponentInBatch();
        void DeleteComponentInBatch();

    private:

        //从本地缓存删除构件
        bool DeleteComponentFromLocal(IProjectComponent * pComponent);
        void RemoveCategoryNoChild(std::vector<std::shared_ptr<IGmepGcsCategory>>& categories);
        void RemoveCategoryNoChild(const CategoryNode& rootNode, std::vector<std::shared_ptr<IGmepGcsCategory>>& categories, std::vector<std::shared_ptr<IGmepGcsCategory>>& newCategories);
        void BuildCategoryTree(CategoryNode& rootNode, const std::vector<std::shared_ptr<IGmepGcsCategory>>& categories);
        void GetComponentCount(CategoryNode& rootNode);
        void GetComponentCount(CategoryNode& rootNode, const std::vector<std::wstring>& vecCategoryCode);
        void CalcComponentCount(CategoryNode& rootNode, const std::map<std::wstring, int>& mapComponentCount);
        void GetComponentCategoryCode(CategoryNode& rootNode, std::vector<std::wstring>& vecCategoryCode);
        void GetComponentList(QModelIndex parentIndex, IPagedData<std::vector<std::shared_ptr<IProjectComponent>>>& pagedComponents);
        void SyncDeletedComponents(const std::vector<IProjectComponent>& compVec);

    private slots: // single operations
        void HandleLoadComponentIntoProject(QAbstractItemModel *model, const QModelIndex &index);
        void HandleSyncComponent(QAbstractItemModel *model, const QModelIndex &index);
        //从本地缓存中进行删除操做
        void HandleDeleteComponentLocal(QAbstractItemModel *model, const QModelIndex &index);
        void HandlePlaceComponent(QAbstractItemModel *model, const QModelIndex &index);
        void HandleComponentSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);

        // 布置 (或载入再布置)流程
        void ProceedPlaceComponentWorkflow(QAbstractItemModel *model, const QModelIndex &index, const IProjectComponent& component, const std::wstring& projectId);

    private: // widgets
        QPointer<ProjectComponentsTableModel> m_pTableModel;
        QPointer<ListItemModel> m_pListModel;
        QPointer<CategoriesTreeView> m_pCategoriesTreeView;
        QPointer<QTableView> m_pTableView;
        QPointer<SearchTextBox> m_pSearchTextBox;
        QPointer<Bubble> m_pKeyWordBubble;
        QPointer<Bubble> m_pCategoryBubble;
        QPointer<Bubble> m_pIsUpdatableOnlyBubble;
        QPointer<QPushButton> m_pBtnClearBubbles;
        QPointer<QLabel> m_pLblResultCount;
        QPointer<Switcher> m_pShowUpdatableOnlySwitcher;
        QPointer<QMenu> m_pMenuAdding;
        QPointer<QPushButton> m_pBtnAdding;
        QPointer<QPushButton> m_pBtnSyncComponenets;
        QPointer<QPushButton> m_pUpdateSelected;
        QPointer<QPushButton> m_pLoadSelected;
        QPointer<QPushButton> m_pDeleteSelected;
        QPointer<QPushButton> m_pCardModeButton;
        QPointer<QPushButton> m_pListModeButton;
        QPointer<QStackedLayout> m_pViewLayout;
        QPointer<ProjectComponentDetailPanel> m_pDetailPanel;
        QPointer<QStackedLayout> m_pContentStackedLayout;

        QPointer<QLayout> m_pBatchOperationLayout;
        QPointer<QVBoxLayout> m_pSubOperationRegionAndOthersLayout;
        QPointer<ProjectComponentsTableHeaderView> m_headerView;
        QPointer<ProjectComponentItemDelegate> m_ItemDelegate;
        QPointer<ListItemDelegate> m_CardItemDelegate;
        QPointer<ListHeaderWidget> m_cardListHeaderWidget;
    private: // filters
        std::wstring m_projectId;
        std::wstring m_enterpriseId;
        Major m_major;
        std::wstring m_keyword;
        std::wstring m_selectedCategoryCode;
        int32_t m_currentPage;
        int32_t m_pageSize;
        int32_t m_sort;
        bool m_bIsUpdatableOnly;

        bool m_isColloaborationDocument = true; // 是否是协同项目

        bool m_isPrivateEnv = false;

    private: 
        SelectionHelper<IProjectComponent> m_componentSelectionHelper;

    };
}